package org.dawning.shop.inventory.command.config;

import com.mongodb.MongoClient;
import org.axonframework.commandhandling.distributed.CommandBusConnector;
import org.axonframework.commandhandling.distributed.CommandRouter;
import org.axonframework.commandhandling.distributed.DistributedCommandBus;
import org.axonframework.commandhandling.model.Repository;
import org.axonframework.eventsourcing.*;
import org.axonframework.eventsourcing.eventstore.EventStorageEngine;
import org.axonframework.eventsourcing.eventstore.EventStore;
import org.axonframework.mongo.DefaultMongoTemplate;
import org.axonframework.mongo.MongoTemplate;
import org.axonframework.mongo.eventsourcing.eventstore.MongoEventStorageEngine;
import org.axonframework.serialization.json.JacksonSerializer;
import org.dawning.shop.inventory.command.aggregate.InventoryAggregate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;


/**
 * Created by Cc on 2017/6/8.
 */
@Configuration
public class AxonConfiguration {

    @Autowired
    private MongoClient mongo;

    @Bean(name = "axonMongoTemplate")
    MongoTemplate axonMongoTemplate() {
        return new DefaultMongoTemplate(mongo,"scene-shop");
    }

    @Autowired
    @Qualifier("axonMongoTemplate")
    private MongoTemplate mongoTemplate;

    @Bean
    EventStorageEngine eventStorageEngine() {

        return new MongoEventStorageEngine(mongoTemplate);
    }

    /*@Primary // to make sure this CommandBus implementation is used for autowiring
    @Bean
    public DistributedCommandBus distributedCommandBus(CommandRouter commandRouter,
                                                       CommandBusConnector commandBusConnector) {
        return new DistributedCommandBus(commandRouter, commandBusConnector);
    }*/

    @Bean
    public GenericAggregateFactory<InventoryAggregate> genericAggregateFactory(){
        return new GenericAggregateFactory<>(InventoryAggregate.class);
    }

    @Bean
    public Snapshotter snapshotter(EventStore eventStore){
        return new AggregateSnapshotter(eventStore, genericAggregateFactory());
    }

    @Bean
    public SnapshotTriggerDefinition snapshotTriggerDefinition(EventStore eventStore){
        return new EventCountSnapshotTriggerDefinition(snapshotter(eventStore),10);
    }

    //事件仓储
    @Bean
    public Repository<InventoryAggregate> inventoryAggregateRepository(EventStore eventStore){
        return new EventSourcingRepository<>(InventoryAggregate.class, eventStore, snapshotTriggerDefinition(eventStore));
    }
}
